Software Setup

Installing Library

To use the AVR programming library you'll need to install the Adafruit CircuitPython AVRprog library on your CircuitPython board.

First make sure you are running the latest version of Adafruit CircuitPython for your board.

Next you'll need to install the necessary libraries to use the hardware--carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle.  Our introduction guide has a great page on how to install the library bundle for both express and non-express boards.

Remember for non-express boards like the Trinket M0, you'll need to manually install the necessary library from the bundle:

  • adafruit_avrprog.mpy

You can also download the adafruit_avrprog.mpy from its releases page on Github.

Before continuing make sure your board's lib folder or root filesystem has the adafruit_avrprog.mpy file copied over.

Next connect to the board's serial REPL so you are at the CircuitPython >>> prompt.

For this simple example, we're assuming you don't need a clock-driving pin here, if you do, see the full example at the end of the page!

Imports

You'll need to import a few libraries

  • board - for assigning hardware pins
  • busio - we use SPI bus to talk to the target device
  • adafruit_avrprog - the library that we're using!
>>> import board
>>> import busio
>>> import adafruit_avrprog

Initialize hardware

Next, create the hardware interface, you'll need an SPI port and one extra pin for the reset line. We'll use board.D5 to match our diagrams on the previous page, but it can be any pin you like!

>>> spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
>>> avrprog = adafruit_avrprog.AVRprog()
>>> avrprog.init(spi, board.D5)

Communication / Signature Check

Next we'll verify that we can talk to the chip, once that works we are best off crafting our programmer into a full main.py project but at least we can quickly determine if things worked out.

  1. Start by initializing the programming interface with avrprog.begin() which will pull the reset line low and send some commands to get the chip to listen.
  2. Then read the signature, you'll get an array of numbers - its probably best to turn this into hex values before printing since they're referred to as hex values in datasheets.
  3. Finally, call avrprog.end()
>>> avrprog.begin()
>>> [hex(i) for i in avrprog.read_signature()]
['0x1e', '0x95', '0xf']
>>> avrprog.end()

You can see here we have a 0x1E950F chip attached, also known at an ATmega328P

Full Example

You can save this code to main.py and use the REPL to see the signature data, it also includes the code for setting up the crystal-driving PWM output

"""
Read Signature Test - All this does is read the signature from the chip to
check connectivity!
"""

import board
import busio
import pulseio
import adafruit_avrprog

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
avrprog = adafruit_avrprog.AVRprog()
avrprog.init(spi, board.D5)

# we can generate an 6 MHz clock for driving bare chips too!
clock_pwm = pulseio.PWMOut(board.D9, frequency=6000000, duty_cycle=65536//2)

avrprog.begin()
print("Signature bytes: ", [hex(i) for i in avrprog.read_signature()])
avrprog.end()

SPI / Wiring Errors

If something went wrong, you'll get an SPI transaction failed exception. Check your wiring! Also, sometimes the chip doesn't quite hear us, try connecting again.

Common problems:

  • The target isn't powered - make sure it is powered via USB or via the CircuitPython board. A shared Ground wire is required
  • Make sure you have the reset pin on the target connected to whatever pin you setup when you created the avrprog object
  • On ATmega2560, MOSI and MISO are connected opposite than the way you think. Either way, its OK to try swapping those two wires, see if that helps!
  • The target is expecting a crystal but you don't have one, for example the UNO bootloader requires that the chip have a crystal or oscillator connected up, it's not optional!
Last updated on 2018-01-25 at 06.38.10 PM Published on 2018-01-11 at 08.47.32 PM