Skip to main content

Using AVR ISP MKII to upload firmware to Arduino

HowWhat is AVR ISP MKII?

The AVRISP mkII is a USB-based In-System Programmer (ISP) used to useprogram MatrixPortalAtmel M4(now Microchip) AVR microcontrollers. It's designed for animation

We have another tutorial for setting up the MatrixPortal boarddevelopers and covering the basics. This tutorial will focus on creating an animationhobbyists to displayupload firmware to AVR-based chips directly on a 64x32circuit matrix.board without needing to remove the chip.

IMG_5497.jpgATAVRISP2-1908688492.jpg

CircuitPythonIn this tutorial, we will burn the bootloader to an Arduino UNO (re-upload the firmware to the ATmega328P chip on UNO).

Supported Microcontrollers

It is compatible with a wide range of AVR microcontrollers, including the popular ATmega and librariesATtiny versions
series.

  1. Arduino Uno
  2. Arduino Nano
  3. Arduino Leonardo
  4. Arduino Mega 2560

However, it is not compatible with microcontrollers with ARM-based chips or ESP microcontrollers, such as

  1. Arduino Due
  2. Arduino Zero
  3. Arduino MKR series
  4. Arduino Nano 33 series

Software Compatibility

Works with Atmel Studio (formerly AVR Studio), Arduino IDE and other tools supporting AVR programming. In this tutorial, we arewill be using CircuitPythonArduino 9.0.5 (11/10/2024), all libraries and code used are compatible with this version. Please double-check the latest version of CircuitPython you have installed and use updated and compatible libraries. IDE.

Creating the SpitesheetConnection

A spritesheet is a single image file that contains a collection of smaller images (called sprites) arranged in a grid or some other layout. These individual sprites can represent various frames of an animation, characters, objects, or other visual elements in a video game or graphic application.

We will need to use a bitmap spitesheet. If you just want to test the code, you can download the test.bmp and skip this part for now.

1. Piskel

Piskel is a free online editor for animated sprites & pixel art.

piskel.png

  • GoAVR ISP MKII to resizethe computer using USB B cable
  • 5V power supply for Arduino UNO (target Arduino), can be via USB port
  • AVR ISP MKII 6-pin connector to setArduino ICSP pins (at the canvasbottom size to 64 x 32 px
  • Draw whatever you want
  • Add new frame and draw
  • until you finishusually)

Screenshot 2024-10-11 at 12.04.56.pngArduino+UNO+Pinout-1338624350.png

    Status LEDs

    General speaking, Green = Everything is OK. Red = There is an issue.

    Below is some common examples:

    Everything works fine: AVR_greenLight.jpg

    Missing power supply for target Arduino: AVR_redLight.jpg

    6-pin connection wrong direction: AVR_redLight_2.jpg

    Burn bootloader with Arduino IDE

    1. Go to EXPORTBoard: Choose your target Arduino
    2. Leave the Port empty
    3. Click Burn Bootloader
    4. Select PNG
    5. Change Columns to 1
    6. Download
    7. You now have a very long PNG file

2. Photoshop

bmp format.png

  • Open the image with Photoshop
  • Save a copy in BMP format
  • Choose Windows (doesn't matter what computer you use) and 16 Bit
  • You now have a ready-to-go spitesheet BMP file

Importing the Image

  1. Create a folder called bmp in the CIRCUITPY drive.
  2. Copy the bitmap file you have created into the folder.Done!

Code

arduinoIDEburnbootloader.png

# SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import os
import board
import displayio
from digitalio import DigitalInOut, Pull
from adafruit_matrixportal.matrix import Matrix
from adafruit_debouncer import Debouncer

SPRITESHEET_FOLDER = "/bmp"
DEFAULT_FRAME_DURATION = 0.1  # 100ms

FRAME_DURATION_OVERRIDES = {
    "KIRBY.bmp": 0.05,
}

# --- Display setup ---
matrix = Matrix(width=64, height=64, bit_depth=6)
sprite_group = displayio.Group()
matrix.display.root_group = sprite_group


file_list = sorted(
    [
        f
        for f in os.listdir(SPRITESHEET_FOLDER)
        if (f.endswith(".bmp") and not f.startswith("."))
    ]
)

if len(file_list) == 0:
    raise RuntimeError("No images found")

current_image = None
current_frame = 0
current_loop = 0
frame_count = 0
frame_duration = DEFAULT_FRAME_DURATION
direction = 1 #1 for forward, -1 for backward

def load_image():
    """
    Load an image as a sprite
    """
    # pylint: disable=global-statement
    global current_frame, current_loop, frame_count, frame_duration
    while sprite_group:
        sprite_group.pop()

    filename = SPRITESHEET_FOLDER + "/" + file_list[current_image]


    # # CircuitPython 7+ compatible
    bitmap = displayio.OnDiskBitmap(filename)
    sprite = displayio.TileGrid(
         bitmap,
         pixel_shader=bitmap.pixel_shader,
         tile_width=bitmap.width,
         tile_height=matrix.display.height,
     )

    sprite_group.append(sprite)

    current_frame = 0
    current_loop = 0
    frame_count = int(bitmap.height / matrix.display.height)
    frame_duration = DEFAULT_FRAME_DURATION
    if file_list[current_image] in FRAME_DURATION_OVERRIDES:
        frame_duration = FRAME_DURATION_OVERRIDES[file_list[current_image]]
    direction = 1

def advance_image():
    """
    Advance to the next image in the list and loop back at the end
    """
    # pylint: disable=global-statement
    global current_image
    if current_image is not None:
        current_image += 1
    if current_image is None or current_image >= len(file_list):
        current_image = 0
    load_image()


def advance_frame():
    """
    Advance to the next frame and loop back at the end
    """
    # pylint: disable=global-statement
    global current_frame, current_loop, direction
    current_frame += direction
    if current_frame >= frame_count:
        current_frame = frame_count - 1
        direction = -1  # Reverse direction
    elif current_frame < 0:
        current_frame = 0
        direction = 1  # Forward direction
    sprite_group[0][0] = current_frame



advance_image()

while True:
    advance_frame()
    time.sleep(frame_duration)