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.
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.
- Arduino Uno
- Arduino Nano
- Arduino Leonardo
- Arduino Mega 2560
However, it is not compatible with microcontrollers with ARM-based chips or ESP microcontrollers, such as
- Arduino Due
- Arduino Zero
- Arduino MKR series
- 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.
GoAVR ISP MKII to
the computer using USB B cableresize- 5V power supply for Arduino UNO (target Arduino), can be via USB port
- AVR ISP MKII 6-pin connector to
setArduino ICSP pins (at thecanvasbottomsize to 64 x 32 px Draw whatever you wantAdd new frameand drawuntil you finishusually)
Go to
: Choose your target ArduinoEXPORTBoard- Leave the
Port
empty - Click
Burn Bootloader
SelectPNGChangeColumnsto 1DownloadYou now have a very long PNG file
Status LEDs
General speaking, Green = Everything is OK. Red = There is an issue.
Below is some common examples:
Missing power supply for target Arduino:
6-pin connection wrong direction:
Burn bootloader with Arduino IDE
2. Photoshop
Open the image with PhotoshopSave a copy in BMP formatChooseWindows(doesn't matter what computer you use) and16 BitYou now have a ready-to-go spitesheet BMP file
Importing the Image
Create a folder calledbmpin theCIRCUITPYdrive.Copy the bitmap file you have created into the folder.Done!
Code
# 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)