ATtiny85

ATtiny85 Arduino Getting Started Tutorial, The Smallest Arduino

Attiny85 Arduino:

 

ATtiny85 Arduino Getting Started Tutorial, The Smallest Arduino- I am sure you already know about Arduino Uno and Arduino Nano as these are the most commonly used Arduino boards. And I am sure the majority of you guys might also know about other Arduino boards, like Arduino Mega, Arduino Pro Mini, and Arduino Leonardo, etc; there is a long list of the Arduino boards. There are so many other Arduino boards that are not available in the Arduino boards list like the Seeeduino Xiao which is considered to be the smallest Arduino.

ATtiny85 Arduino vs seeduino xiao

And here is my designed Arduino Pro Micro.

ATtiny85 Arduino

Well I could make it much smaller than the Seeeduino Xiao but, I had to make it slightly bigger for you guys, so that you could easily make it at your home.

ATtiny85 Arduino

Anyway, I want the smallest Arduino even smaller than the Seeeduino Xiao and Arduino Pro Micro. So, I decided to use the ATtiny85 CMOS 8-bit microcontroller as the smallest Arduino. You can clearly see the size difference. We don’t need to add external capacitors, resistors, and a crystal. And it’s going to be the cheapest micro version of the Arduino.

By looking at its size, you might have an idea that it has fewer IO pins, lower speed, less memory, and no USB interface. So, let me tell you beforehand that you cannot create every project with ATtiny85 that you can create using Arduino Uno, Arduino Nano, or Arduino Pro Micro. However, you can still create thousands of projects using ATtiny85.

There are many projects in which you only need to connect 1 or 2 sensors along with a display. Or you may want to control certain loads using an IR remote, an RFID module, or other similar devices. ATtiny85 has digital pins, analog pins, PWM pins, SPI pins, and more. Therefore, you can use the ATtiny85 microcontroller board in more than a million different ways. So, without any further delay let’s get started!!!




Amazon Links:

ATtiny85 Controller

Other Tools and Components:

Top Arduino Sensors:

Super Starter kit for Beginners

Digital Oscilloscopes

Variable Supply

Digital Multimeter

Soldering iron kits

PCB small portable drill machines

*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!



ATtiny85 Technical Specifications:

ATtiny85 Arduino technical specifications

The ATtiny85 is a low-power, high-performance CMOS 8-bit AVR Microcontroller chip developed by Atmel Corporation, and is often used in small and low-power embedded systems. Let’s go through some of its technical specifications.

Key Parameters

Architecture: AVR(Advanced Virtual RISC)

Power Supply voltage: 2.7V to 5.5V

CPU Speed: Up to 20 Mhz

Flash Memory: 8 Kbytes

EEPROM: 512 Bytes

GPIO Pins: 6

Analog Pins: 4

PWM Channels: 2

Interface: USI (Universal Serial Interface)

Operating Temperature Range: -40C to +85C

USB interface: No

The Architecture is AVR (Advanced Virtual RISC). The power supply voltage is from 2.7V to 5.5V. CPU Speed is up to 20 Mhz. Flash Memory is 8 Kbytes. EEPROM is 512 Bytes. GPIO pins are 6. Analog pins are 4. PWM pins are basically two located on pins 0 and 1. But pin 4 can also be used as PWM pin. So, technically you can say it has 3 PWM pins. The interface type is USI (Universal Serial Interface) which can be configured to perform SPI or I2C communications. The temperature Range is from -40C to +85C. And it has no USB interface.

The ATtiny25/45/85 provides the following features: 2/4/8K byte of In-System Programmable Flash, 128/256/512 bytes EEPROM, 128/256/256 bytes SRAM, 6 general purpose I/O lines, 32general purpose working registers, one 8-bit Timer/Counter with compare modes, one 8-bit high speed Timer/Counter, Universal Serial Interface, Internal and External Interrupts, a 4-channel,10-bit ADC, a programmable Watchdog Timer with internal Oscillator, and three software select-able power saving modes. The Idle mode stops the CPU while allowing the SRAM, Timer/Counter, ADC, Analog Comparator, and Interrupt system to continue functioning. The Power-down mode saves the register contents, disabling all chip functions until the next Interrupt or Hardware Reset. The ADC Noise Reduction mode stops the CPU and all I/O modules except ADC, to minimize switching noise during ADC conversions. The device is manufactured using Atmel’s high density non-volatile memory technology. The On-chip ISP Flash allows the Program memory to be re-programmed In-System through an SPI serial interface, by a conventional non-volatile memory programmer or by an On-chip boot code running on the AVR core.



ATtiny85 Pinout:

You can follow these Pinout diagrams.

ATtiny85 Arduino pinout

Now, we are going to get it ready; So that we can program it using the Arduino IDE. And for this, we will have to Burn the Bootloader. So, let’s go ahead and do it.

Altium Designer + Altium 365 + Octopart:

Arduino LoRa Free SMS

Altium 365 lets you hold the fastest design reviews ever. Share your designs from anywhere and with anyone with a single click. it’s easy, leave a comment tagging your teammate and they’ll instantly receive an email with a link to the design. Anyone you invite can open the design using a web browser. Using the browser interface, you’re able to comment, markup, cross probe, inspect, and more. Comments are attached directly to the project, making them viewable within Altium designer as well as through the browser interface. Design, share, and manufacture, all in the same space with nothing extra to install or configure. Connect to the platform directly from Altium Designer without changing how you already design electronics. Altium 365 requires no additional licenses and comes included with your subscription plan.

Get real-time component insights as you design with Octopart built into Altium 365. Octopart is the fastest search engine for electronic parts and gives you the most up-to-date part data like specs, datasheets, cad models, and how much the part costs at different amounts etc. Right in the design environment so you can focus on your designs. Start with Altium Designer and Activate Altium 365. Search for electronic parts on Octopart.



ATtiny85 Bootloader Setup:

To burn the Bootloader on the ATtiny85 microcontroller you will need to follow these connections.

ATtiny85 Arduino bootloader circuit

  • Connect pin 1 of the ATtiny85 which is also the reset pin to pin 10 of the Arduino which is the SS (Slave Select).
  • Connect pin 4 which is the ground pin to the Ground pin of the Arduino.
  • Connect pin 5 which is the MOSI pin to pin 11 of the Arduino which is the MOSI (Master-out, Slave In).
  • Connect pin 6 which is the MISO pin to pin 12 of the Arduino which is the MISO (Maser-In, Slave Out).
  • Connect pin 7 which is the SCK pin to pin 13 of the Arduino which is the SCK (Serial Clock).
  • Connect pin 8 of the ATtiny85 which is the VCC pin to the Arduino 5V pin.
  • Finally, connect a 10uF capacitor between the Reset and GND pins of the Arduino. Make sure you connect the +Ve leg of the capacitor with the Reset pin and the other leg of the capacitor with the GND. So, that’s all about the connections.

ATtiny85 Arduino

Now, let’s go ahead and start with the Arduino IDE.




ATtiny85 in Arduino IDE:

The ATtiny85 microcontroller is not pre-installed in the Arduino IDE and you can confirm this by going to the Tools Menu and then to board, you will see a long list of the Arduino boards, but you won’t find ATtiny85. So, this means you will have to manually install the ATtiny85 as a board in the Arduino IDE.

For this, copy the board manager URL link given below.

https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json

Then come back to the Arduino IDE, go to the File Menu, and then to Preferences, and paste the link in the Additional Boards Manager URLs.

ATtiny85 Arduino manager url link

Put a comma if you have added other boards otherwise you can directly paste the board URL link and then click on the OK button.

Go to the Tools Menu, then to board, and click on the Boards Manager. Search for the ATtiny and install it.

ATtiny85 Arduino board download

You can see the ATtiny85 is included in this boards Package. Anyway, you can see I have already installed this board.

Now, to confirm that the ATtiny85 Microcontroller is added, go to the Tools Menu, then to Board and you can see the ATtinny Microcontrollers.

ATtiny85 Arduino in ide

You can see different variants of the ATtiny microcontrollers. So, let’s go ahead and select the ATtiny85 controller. So, our setup on the Arduino IDE is completed.

Next, we are going to connect Arduino Uno with the Laptop. While the Arduino IDE is open, go to the File Menu, then to Examples, and open the ArduinoISP.

ATtiny85 Arduino isp library

ArduinoISP
// Copyright (c) 2008-2011 Randall Bohn
// If you require a license, see
// https://opensource.org/licenses/bsd-license.php
//
// This sketch turns the Arduino into a AVRISP using the following Arduino pins:
//
// Pin 10 is used to reset the target microcontroller.
//
// By default, the hardware SPI pins MISO, MOSI and SCK are used to communicate
// with the target. On all Arduinos, these pins can be found
// on the ICSP/SPI header:
//
//               MISO °. . 5V (!) Avoid this pin on Due, Zero...
//               SCK   . . MOSI
//                     . . GND
//
// On some Arduinos (Uno,...), pins MOSI, MISO and SCK are the same pins as
// digital pin 11, 12 and 13, respectively. That is why many tutorials instruct
// you to hook up the target to these pins. If you find this wiring more
// practical, have a define USE_OLD_STYLE_WIRING. This will work even when not
// using an Uno. (On an Uno this is not needed).
//
// Alternatively you can use any other digital pin by configuring
// software ('BitBanged') SPI and having appropriate defines for PIN_MOSI,
// PIN_MISO and PIN_SCK.
//
// IMPORTANT: When using an Arduino that is not 5V tolerant (Due, Zero, ...) as
// the programmer, make sure to not expose any of the programmer's pins to 5V.
// A simple way to accomplish this is to power the complete system (programmer
// and target) at 3V3.
//
// Put an LED (with resistor) on the following pins:
// 9: Heartbeat   - shows the programmer is running
// 8: Error       - Lights up if something goes wrong (use red if that makes sense)
// 7: Programming - In communication with the slave
//

#include "Arduino.h"
#undef SERIAL


#define PROG_FLICKER true

// Configure SPI clock (in Hz).
// E.g. for an ATtiny @ 128 kHz: the datasheet states that both the high and low
// SPI clock pulse must be > 2 CPU cycles, so take 3 cycles i.e. divide target
// f_cpu by 6:
//     #define SPI_CLOCK            (128000/6)
//
// A clock slow enough for an ATtiny85 @ 1 MHz, is a reasonable default:

#define SPI_CLOCK 		(1000000/6)


// Select hardware or software SPI, depending on SPI clock.
// Currently only for AVR, for other architectures (Due, Zero,...), hardware SPI
// is probably too fast anyway.

#if defined(ARDUINO_ARCH_AVR)

  #if SPI_CLOCK > (F_CPU / 128)
    #define USE_HARDWARE_SPI
  #endif

#endif

// Configure which pins to use:

// The standard pin configuration.
#ifndef ARDUINO_HOODLOADER2

  #define RESET     10 // Use pin 10 to reset the target rather than SS
  #define LED_HB    9
  #define LED_ERR   8
  #define LED_PMODE 7

  // Uncomment following line to use the old Uno style wiring
  // (using pin 11, 12 and 13 instead of the SPI header) on Leonardo, Due...

  // #define USE_OLD_STYLE_WIRING

  #ifdef USE_OLD_STYLE_WIRING

    #define PIN_MOSI	11
    #define PIN_MISO	12
    #define PIN_SCK		13

  #endif

  // HOODLOADER2 means running sketches on the ATmega16U2 serial converter chips
  // on Uno or Mega boards. We must use pins that are broken out:
#else

  #define RESET     	4
  #define LED_HB    	7
  #define LED_ERR   	6
  #define LED_PMODE 	5

#endif

// By default, use hardware SPI pins:
#ifndef PIN_MOSI
  #define PIN_MOSI 	MOSI
#endif

#ifndef PIN_MISO
  #define PIN_MISO 	MISO
#endif

#ifndef PIN_SCK
  #define PIN_SCK 	SCK
#endif

// Force bitbanged SPI if not using the hardware SPI pins:
#if (PIN_MISO != MISO) ||  (PIN_MOSI != MOSI) || (PIN_SCK != SCK)
  #undef USE_HARDWARE_SPI
#endif


// Configure the serial port to use.
//
// Prefer the USB virtual serial port (aka. native USB port), if the Arduino has one:
//   - it does not autoreset (except for the magic baud rate of 1200).
//   - it is more reliable because of USB handshaking.
//
// Leonardo and similar have an USB virtual serial port: 'Serial'.
// Due and Zero have an USB virtual serial port: 'SerialUSB'.
//
// On the Due and Zero, 'Serial' can be used too, provided you disable autoreset.
// To use 'Serial': #define SERIAL Serial

#ifdef SERIAL_PORT_USBVIRTUAL
  #define SERIAL SERIAL_PORT_USBVIRTUAL
#else
  #define SERIAL Serial
#endif


// Configure the baud rate:

#define BAUDRATE	19200
// #define BAUDRATE	115200
// #define BAUDRATE	1000000


#define HWVER 2
#define SWMAJ 1
#define SWMIN 18

// STK Definitions
#define STK_OK      0x10
#define STK_FAILED  0x11
#define STK_UNKNOWN 0x12
#define STK_INSYNC  0x14
#define STK_NOSYNC  0x15
#define CRC_EOP     0x20 //ok it is a space...

void pulse(int pin, int times);

#ifdef USE_HARDWARE_SPI
#include "SPI.h"
#else

#define SPI_MODE0 0x00

#if !defined(ARDUINO_API_VERSION) || ARDUINO_API_VERSION != 10001 // A SPISettings class is declared by ArduinoCore-API 1.0.1
class SPISettings {
  public:
    // clock is in Hz
    SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) : clockFreq(clock) {
      (void) bitOrder;
      (void) dataMode;
    };

    uint32_t getClockFreq() const {
      return clockFreq;
    }

  private:
    uint32_t clockFreq;
};
#endif  // !defined(ARDUINO_API_VERSION)

class BitBangedSPI {
  public:
    void begin() {
      digitalWrite(PIN_SCK, LOW);
      digitalWrite(PIN_MOSI, LOW);
      pinMode(PIN_SCK, OUTPUT);
      pinMode(PIN_MOSI, OUTPUT);
      pinMode(PIN_MISO, INPUT);
    }

    void beginTransaction(SPISettings settings) {
      pulseWidth = (500000 + settings.getClockFreq() - 1) / settings.getClockFreq();
      if (pulseWidth == 0) {
        pulseWidth = 1;
      }
    }

    void end() {}

    uint8_t transfer(uint8_t b) {
      for (unsigned int i = 0; i < 8; ++i) {
        digitalWrite(PIN_MOSI, (b & 0x80) ? HIGH : LOW);
        digitalWrite(PIN_SCK, HIGH);
        delayMicroseconds(pulseWidth);
        b = (b << 1) | digitalRead(PIN_MISO);
        digitalWrite(PIN_SCK, LOW); // slow pulse
        delayMicroseconds(pulseWidth);
      }
      return b;
    }

  private:
    unsigned long pulseWidth; // in microseconds
};

static BitBangedSPI SPI;

#endif

void setup() {
  SERIAL.begin(BAUDRATE);

  pinMode(LED_PMODE, OUTPUT);
  pulse(LED_PMODE, 2);
  pinMode(LED_ERR, OUTPUT);
  pulse(LED_ERR, 2);
  pinMode(LED_HB, OUTPUT);
  pulse(LED_HB, 2);

}

int ISPError = 0;
int pmode = 0;
// address for reading and writing, set by 'U' command
unsigned int here;
uint8_t buff[256]; // global block storage

#define beget16(addr) (*addr * 256 + *(addr+1) )
typedef struct param {
  uint8_t devicecode;
  uint8_t revision;
  uint8_t progtype;
  uint8_t parmode;
  uint8_t polling;
  uint8_t selftimed;
  uint8_t lockbytes;
  uint8_t fusebytes;
  uint8_t flashpoll;
  uint16_t eeprompoll;
  uint16_t pagesize;
  uint16_t eepromsize;
  uint32_t flashsize;
}
parameter;

parameter param;

// this provides a heartbeat on pin 9, so you can tell the software is running.
uint8_t hbval = 128;
int8_t hbdelta = 8;
void heartbeat() {
  static unsigned long last_time = 0;
  unsigned long now = millis();
  if ((now - last_time) < 40) {
    return;
  }
  last_time = now;
  if (hbval > 192) {
    hbdelta = -hbdelta;
  }
  if (hbval < 32) {
    hbdelta = -hbdelta;
  }
  hbval += hbdelta;
  analogWrite(LED_HB, hbval);
}

static bool rst_active_high;

void reset_target(bool reset) {
  digitalWrite(RESET, ((reset && rst_active_high) || (!reset && !rst_active_high)) ? HIGH : LOW);
}

void loop(void) {
  // is pmode active?
  if (pmode) {
    digitalWrite(LED_PMODE, HIGH);
  } else {
    digitalWrite(LED_PMODE, LOW);
  }
  // is there an error?
  if (ISPError) {
    digitalWrite(LED_ERR, HIGH);
  } else {
    digitalWrite(LED_ERR, LOW);
  }

  // light the heartbeat LED
  heartbeat();
  if (SERIAL.available()) {
    avrisp();
  }
}

uint8_t getch() {
  while (!SERIAL.available());
  return SERIAL.read();
}
void fill(int n) {
  for (int x = 0; x < n; x++) {
    buff[x] = getch();
  }
}

#define PTIME 30
void pulse(int pin, int times) {
  do {
    digitalWrite(pin, HIGH);
    delay(PTIME);
    digitalWrite(pin, LOW);
    delay(PTIME);
  } while (times--);
}

void prog_lamp(int state) {
  if (PROG_FLICKER) {
    digitalWrite(LED_PMODE, state);
  }
}

uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
  SPI.transfer(a);
  SPI.transfer(b);
  SPI.transfer(c);
  return SPI.transfer(d);
}

void empty_reply() {
  if (CRC_EOP == getch()) {
    SERIAL.print((char)STK_INSYNC);
    SERIAL.print((char)STK_OK);
  } else {
    ISPError++;
    SERIAL.print((char)STK_NOSYNC);
  }
}

void breply(uint8_t b) {
  if (CRC_EOP == getch()) {
    SERIAL.print((char)STK_INSYNC);
    SERIAL.print((char)b);
    SERIAL.print((char)STK_OK);
  } else {
    ISPError++;
    SERIAL.print((char)STK_NOSYNC);
  }
}

void get_version(uint8_t c) {
  switch (c) {
    case 0x80:
      breply(HWVER);
      break;
    case 0x81:
      breply(SWMAJ);
      break;
    case 0x82:
      breply(SWMIN);
      break;
    case 0x93:
      breply('S'); // serial programmer
      break;
    default:
      breply(0);
  }
}

void set_parameters() {
  // call this after reading parameter packet into buff[]
  param.devicecode = buff[0];
  param.revision   = buff[1];
  param.progtype   = buff[2];
  param.parmode    = buff[3];
  param.polling    = buff[4];
  param.selftimed  = buff[5];
  param.lockbytes  = buff[6];
  param.fusebytes  = buff[7];
  param.flashpoll  = buff[8];
  // ignore buff[9] (= buff[8])
  // following are 16 bits (big endian)
  param.eeprompoll = beget16(&buff[10]);
  param.pagesize   = beget16(&buff[12]);
  param.eepromsize = beget16(&buff[14]);

  // 32 bits flashsize (big endian)
  param.flashsize = buff[16] * 0x01000000
                    + buff[17] * 0x00010000
                    + buff[18] * 0x00000100
                    + buff[19];

  // AVR devices have active low reset, AT89Sx are active high
  rst_active_high = (param.devicecode >= 0xe0);
}

void start_pmode() {

  // Reset target before driving PIN_SCK or PIN_MOSI

  // SPI.begin() will configure SS as output, so SPI master mode is selected.
  // We have defined RESET as pin 10, which for many Arduinos is not the SS pin.
  // So we have to configure RESET as output here,
  // (reset_target() first sets the correct level)
  reset_target(true);
  pinMode(RESET, OUTPUT);
  SPI.begin();
  SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0));

  // See AVR datasheets, chapter "SERIAL_PRG Programming Algorithm":

  // Pulse RESET after PIN_SCK is low:
  digitalWrite(PIN_SCK, LOW);
  delay(20); // discharge PIN_SCK, value arbitrarily chosen
  reset_target(false);
  // Pulse must be minimum 2 target CPU clock cycles so 100 usec is ok for CPU
  // speeds above 20 KHz
  delayMicroseconds(100);
  reset_target(true);

  // Send the enable programming command:
  delay(50); // datasheet: must be > 20 msec
  spi_transaction(0xAC, 0x53, 0x00, 0x00);
  pmode = 1;
}

void end_pmode() {
  SPI.end();
  // We're about to take the target out of reset so configure SPI pins as input
  pinMode(PIN_MOSI, INPUT);
  pinMode(PIN_SCK, INPUT);
  reset_target(false);
  pinMode(RESET, INPUT);
  pmode = 0;
}

void universal() {
  uint8_t ch;

  fill(4);
  ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]);
  breply(ch);
}

void flash(uint8_t hilo, unsigned int addr, uint8_t data) {
  spi_transaction(0x40 + 8 * hilo,
                  addr >> 8 & 0xFF,
                  addr & 0xFF,
                  data);
}
void commit(unsigned int addr) {
  if (PROG_FLICKER) {
    prog_lamp(LOW);
  }
  spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
  if (PROG_FLICKER) {
    delay(PTIME);
    prog_lamp(HIGH);
  }
}

unsigned int current_page() {
  if (param.pagesize == 32) {
    return here & 0xFFFFFFF0;
  }
  if (param.pagesize == 64) {
    return here & 0xFFFFFFE0;
  }
  if (param.pagesize == 128) {
    return here & 0xFFFFFFC0;
  }
  if (param.pagesize == 256) {
    return here & 0xFFFFFF80;
  }
  return here;
}


void write_flash(int length) {
  fill(length);
  if (CRC_EOP == getch()) {
    SERIAL.print((char) STK_INSYNC);
    SERIAL.print((char) write_flash_pages(length));
  } else {
    ISPError++;
    SERIAL.print((char) STK_NOSYNC);
  }
}

uint8_t write_flash_pages(int length) {
  int x = 0;
  unsigned int page = current_page();
  while (x < length) {
    if (page != current_page()) {
      commit(page);
      page = current_page();
    }
    flash(LOW, here, buff[x++]);
    flash(HIGH, here, buff[x++]);
    here++;
  }

  commit(page);

  return STK_OK;
}

#define EECHUNK (32)
uint8_t write_eeprom(unsigned int length) {
  // here is a word address, get the byte address
  unsigned int start = here * 2;
  unsigned int remaining = length;
  if (length > param.eepromsize) {
    ISPError++;
    return STK_FAILED;
  }
  while (remaining > EECHUNK) {
    write_eeprom_chunk(start, EECHUNK);
    start += EECHUNK;
    remaining -= EECHUNK;
  }
  write_eeprom_chunk(start, remaining);
  return STK_OK;
}
// write (length) bytes, (start) is a byte address
uint8_t write_eeprom_chunk(unsigned int start, unsigned int length) {
  // this writes byte-by-byte, page writing may be faster (4 bytes at a time)
  fill(length);
  prog_lamp(LOW);
  for (unsigned int x = 0; x < length; x++) {
    unsigned int addr = start + x;
    spi_transaction(0xC0, (addr >> 8) & 0xFF, addr & 0xFF, buff[x]);
    delay(45);
  }
  prog_lamp(HIGH);
  return STK_OK;
}

void program_page() {
  char result = (char) STK_FAILED;
  unsigned int length = 256 * getch();
  length += getch();
  char memtype = getch();
  // flash memory @here, (length) bytes
  if (memtype == 'F') {
    write_flash(length);
    return;
  }
  if (memtype == 'E') {
    result = (char)write_eeprom(length);
    if (CRC_EOP == getch()) {
      SERIAL.print((char) STK_INSYNC);
      SERIAL.print(result);
    } else {
      ISPError++;
      SERIAL.print((char) STK_NOSYNC);
    }
    return;
  }
  SERIAL.print((char)STK_FAILED);
  return;
}

uint8_t flash_read(uint8_t hilo, unsigned int addr) {
  return spi_transaction(0x20 + hilo * 8,
                         (addr >> 8) & 0xFF,
                         addr & 0xFF,
                         0);
}

char flash_read_page(int length) {
  for (int x = 0; x < length; x += 2) {
    uint8_t low = flash_read(LOW, here);
    SERIAL.print((char) low);
    uint8_t high = flash_read(HIGH, here);
    SERIAL.print((char) high);
    here++;
  }
  return STK_OK;
}

char eeprom_read_page(int length) {
  // here again we have a word address
  int start = here * 2;
  for (int x = 0; x < length; x++) {
    int addr = start + x;
    uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF);
    SERIAL.print((char) ee);
  }
  return STK_OK;
}

void read_page() {
  char result = (char)STK_FAILED;
  int length = 256 * getch();
  length += getch();
  char memtype = getch();
  if (CRC_EOP != getch()) {
    ISPError++;
    SERIAL.print((char) STK_NOSYNC);
    return;
  }
  SERIAL.print((char) STK_INSYNC);
  if (memtype == 'F') {
    result = flash_read_page(length);
  }
  if (memtype == 'E') {
    result = eeprom_read_page(length);
  }
  SERIAL.print(result);
}

void read_signature() {
  if (CRC_EOP != getch()) {
    ISPError++;
    SERIAL.print((char) STK_NOSYNC);
    return;
  }
  SERIAL.print((char) STK_INSYNC);
  uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00);
  SERIAL.print((char) high);
  uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
  SERIAL.print((char) middle);
  uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00);
  SERIAL.print((char) low);
  SERIAL.print((char) STK_OK);
}
//////////////////////////////////////////
//////////////////////////////////////////


////////////////////////////////////
////////////////////////////////////
void avrisp() {
  uint8_t ch = getch();
  switch (ch) {
    case '0': // signon
      ISPError = 0;
      empty_reply();
      break;
    case '1':
      if (getch() == CRC_EOP) {
        SERIAL.print((char) STK_INSYNC);
        SERIAL.print("AVR ISP");
        SERIAL.print((char) STK_OK);
      } else {
        ISPError++;
        SERIAL.print((char) STK_NOSYNC);
      }
      break;
    case 'A':
      get_version(getch());
      break;
    case 'B':
      fill(20);
      set_parameters();
      empty_reply();
      break;
    case 'E': // extended parameters - ignore for now
      fill(5);
      empty_reply();
      break;
    case 'P':
      if (!pmode) {
        start_pmode();
      }
      empty_reply();
      break;
    case 'U': // set address (word)
      here = getch();
      here += 256 * getch();
      empty_reply();
      break;

    case 0x60: //STK_PROG_FLASH
      getch(); // low addr
      getch(); // high addr
      empty_reply();
      break;
    case 0x61: //STK_PROG_DATA
      getch(); // data
      empty_reply();
      break;

    case 0x64: //STK_PROG_PAGE
      program_page();
      break;

    case 0x74: //STK_READ_PAGE 't'
      read_page();
      break;

    case 'V': //0x56
      universal();
      break;
    case 'Q': //0x51
      ISPError = 0;
      end_pmode();
      empty_reply();
      break;

    case 0x75: //STK_READ_SIGN 'u'
      read_signature();
      break;

    // expecting a command, not CRC_EOP
    // this is how we can get back in sync
    case CRC_EOP:
      ISPError++;
      SERIAL.print((char) STK_NOSYNC);
      break;

    // anything else we will return STK_UNKNOWN
    default:
      ISPError++;
      if (CRC_EOP == getch()) {
        SERIAL.print((char)STK_UNKNOWN);
      } else {
        SERIAL.print((char)STK_NOSYNC);
      }
  }
}

Next, select the communication port. Next, select the Programmer “Arduino as ISP”. Finally, click on the Burn Bootloader.

ATtiny85 Arduino burn bootloader

During the Bootloader burning, you will see flashing Leds on the Arduino Uno. The Bootloader burning process is going to take a few seconds. Once the Bootloader burning process is completed, the flashing Leds on the Arduino Uno will stop, and you will also see a message in the Arduino IDE. If it doesn’t make any sense to you, then you can watch my video tutorial given at the end of this article.

So, the Bootloader burning process is completed and now we are going to check if we can program the smallest Arduino “ATtiny85” using the Arduino IDE. So, let’s go ahead and control an LED.

Note: While burning the bootloader if it gives you an error, no need to panic, you can retry by clicking on the Burn Bootloader.



LED with ATtiny85:

ATtiny85 Arduino simple led project

Connect your power source voltage and GND wires with the VCC and GND pins of the ATtiny85 microcontroller. The voltage should be from 2.7V to 5.5 volts. In the circuit diagram you can see two batteries. But you can use a 3.7V lipo battery or any other 5V regulated power supply.

Connect the Anode leg of the Led to pin 5(physical pin number) which is the digital pin 0. So, In the programming, we will refer to the physical pin 5 as pin 0. I am sure you got my point. Anyway, don’t forget to add a current limiting resistor of 330 ohms. And connect the Cathode leg of the LED with the GND.

ATtiny85 Arduino led blinking example

Now, let’s go ahead and take a look at the LED blinking program.



LED Blinking ATtiny85 Arduino Code:

// the setup function runs once when you press reset or power the board

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(0, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}

This is the most basic LED blinking code. You can see, I have used the Digital pin 0 as the output to control an LED. And in the loop() function, you can see I am just turning ON and turn OFF the LED at a delay of 1 second. So, let’s go ahead and upload this program.

ATtiny85 Arduino

Right, now you can see the LED is not connected. And these are the same exact connections that I used for burning the Bootloader. So, we are going to use the Arduino Uno for uploading the program. So, to upload the program, I simply click on the Upload button. After uploading the code, next, I removed all the wires.

ATtiny85 Arduino project for beginners

I connected my 2.5V LED with the ATtiny85 as per the circuit diagram. And I am going to use my designed 5V and 3A power supply. This power supply takes up to 28 volts input and on the output it gives regulated 5 volts. So, with this power supply we can power up the ATtiny85 controller using Solar panels, Batteries, and other DC adaptors. You can watch my video on how to make this amazing 5V and 3A power supply. So, let’s go ahead and power up the smallest Arduino based on the ATtiny85 microcontroller.

ATtiny85 Arduino led blinking project

You can see the LED is blinking which means we have done everything correctly. In my upcoming videos, I will use the ATtiny85 controller in intermediate and advanced level projects. So, that’s all for now.



Watch Video Tutorial:

https://youtu.be/akUUHkYS-yE

 

Engr Fahad

My name is Shahzada Fahad and I am an Electrical Engineer. I have been doing Job in UAE as a site engineer in an Electrical Construction Company. Currently, I am running my own YouTube channel "Electronic Clinic", and managing this Website. My Hobbies are * Watching Movies * Music * Martial Arts * Photography * Travelling * Make Sketches and so on...

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button