This is a small experiment to create a driver-less gamepad from an ATtiny84 (using external crystal) or an ATtiny85 (using internal PLL clock).
First, reproduce the hardware setup, as described in schema/internal.pdf
.
Then, connect your ISP (provided makefile assumes Arduino as ISP on COM3).
Go to the code/internal
subfolder and run:
make
make flash
make upload
You can test the gamepad using this website.
A few notes regarding hardware components:
- The system operates at 5v, as provided by USB host.
- As suggested by V-USB documentation, two 3.6V zener diodes are used to limit voltage of D- and D+.
- A pull-up (through a 1.5kOhm resistor) is applied on D-, to announce low speed.
- Do not forget to also connect D+ to
INT0
(or to rearrange pins a bit). - If the pins on which D- or D+ are connected are also used to program the ATtiny, make sure to disconnect the programmer.
- 10k resistors are used as pull-up/-down to avoid dangling pins.
- De-coupling capacitors are used on USB's VCC and near the ATtiny.
ATTiny84 variant:
- An external 16MHz crystal is used instead of internal clock, as the ATtiny84 internal clock cannot reach minimum requirements.
ATtiny85 variant:
- The internal PLL clock is set to 16MHz, and then over-clocked using OSCCAL.
For more details, please refer to the schematics in the schema
folder.
A few notes regarding software components:
- Using V-USB (2012-12-06).
- The following constants have been modified in
usbconfig.h
:USB_CFG_IOPORTNAME
,USB_CFG_DMINUS_BIT
andUSB_CFG_DPLUS_BIT
, to match the schematic.USB_CFG_HAVE_INTRIN_ENDPOINT
andUSB_CFG_INTR_POLL_INTERVAL
, to enable interruptions.USB_CFG_MAX_BUS_POWER
, to announce low consumption.USB_CFG_DEVICE_NAME
andUSB_CFG_DEVICE_NAME_LEN
, set toGamepad
.USB_CFG_DEVICE_CLASS
andUSB_CFG_INTERFACE_CLASS
, to enable HID descriptor.USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
, which match our HID in the code.
- HID descriptor made using HID Descriptor Tool.
- The HID interface is a gamepad with a single button (note the 7 bits of padding).
- Watchdog timer is enabled, to allow automatic reboot on freeze.
- The makefile assuming that the AVR toolchain is available in the path (e.g. the ones shipped with Arduino IDE).
- Using
avrdude.conf
andempty_all.hex
from ATTinyCore (1.4.1).
ATtiny85 variant:
- In
usbconfig.h
:USB_RESET_HOOK
is uncommented, and a forward definition forhadUsbReset
is provided.USB_CFG_HAVE_MEASURE_FRAME_LENGTH
, to defineusbMeasureFrameLength
, which is used to callibrate the clock.
- In
main.c
,hadUsbReset
is implemented. A binary search is done to reach 16.5MHz by tweaking OSCCAL. The code is taken from this blog.
This section provides basic instructions, where some of them are actually unnecessary for this project. Hopefully it will help somebody in the future...
Tested with Arduino IDE 1.8.13 and ATTinyCore 1.4.1
First, we need to install a dedicated board manager, to handle the ATTiny family. The ATTinyCore project provides the necessary tools to use Arduino as ISP for an ATTiny84.
- In
File >> Preferences
, add this link to the Additional Boards Manager URLs:http://drazzy.com/package_drazzy.com_index.json
- In
Tools >> Board >> Board Manager
, install theATTinyCore
package bySpence Konde
.
Then, install Arduino ISP sketch:
- Connect the Arduino Micro using USB.
- Load the ArduinoISP example (
File >> Examples >> ArduinoISP
). - In
Tools >> Board
, selectArduino Micro
. - In
Tools >> Port
, select the desired Arduino Micro. - In
Tools >> Programmer
, selectAVR ISP
(default). - Select
Sketch >> Upload
.
Finally, burn the desired code to the ATTiny84. As an example, you can use Examples >> 01.Basics >> Blink
, where you need to replace LED_BUILTIN
by 0
.
- In
Tools >> Board >> ATTinyCore
, selectATTiny24/44/84(a) (No bootloader)
. - In
Tools >> Chip
, selectATTiny84(a)
. - In
Tools >> Clock
, select1MHz (internal)
. - In
Tools >> Programmer
, selectArduino as ISP (ATmega32U4, ATTinyCore)
. - Select
Tools >> Burn Bootloader
to set ATtiny's fuses. - Select
Sketch >> Upload
.
For more details, see this page.
You might want to enable verbosity in File > Preferences
, which shows actual commands sent with avrdude
in Arduino IDE
Still assuming Arduino as ISP, you can use avrdude
to interact with the ATtiny84 directly.
Here we read the values of the fuses:
cd <arduino>/hardware/tools/avr/bin
./avrdude \
-C <user>/AppData/Local/Arduino15/packages/ATTinyCore/hardware/avr/1.4.1/avrdude.conf \
-v \
-p attiny84 \
-c arduino \
-P COM3 \
-b 19200 \
-U lfuse:r:-:i
See this page for more fuse manipulation.
You can also directly send some hex file you compiled manually. See the manual for details.
The serial package can be used to communicate directly with a device on a COM port.
from serial.tools.list_ports import comports
ports = comports()
port = ports[0]
...
- V-USB-related
- https://www.obdev.at/products/vusb/index.html
- https://codeandlife.com/2012/01/22/avr-attiny-usb-tutorial-part-1/
- https://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/
- https://www.insidegadgets.com/2011/05/08/playing-around-with-v-usb-for-avr/
- https://www.snrelectronicsblog.com/arduino/attiny85-based-universal-pc-remote/
- https://www.morethantechnical.com/2014/06/24/simple-attiny85-usb-board/
- http://dangerousprototypes.com/blog/2010/04/29/prototype-bus-pirate-v3b/
- https://github.com/TechFactoryHU/vusb-arduino
- https://github.com/robsoncouto/usbasp2gamepad
- ATtiny clocks and fuses
- https://github.com/SpenceKonde/ATTinyCore
- https://www.hackster.io/porrey/attiny-16mhz-610d41
- https://www.microrusty.com/mediawiki/index.php/AVRDUDE_Attiny84_Fuses
- https://www.ladyada.net/learn/avr/fuses.html
- https://embedderslife.wordpress.com/2012/08/20/fuse-bits-arent-that-scary/
- https://hackaday.com/2012/08/30/avr-fuse-bits-explained/
- http://eleccelerator.com/fusecalc/fusecalc.php?chip=attiny84
- https://www.insidegadgets.com/2011/05/16/change-attiny85-clock-speed-on-the-fly/
- https://www.ladyada.net/learn/proj1/blinky.html